/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.be;


import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.exceptions.BefEngineException;
import com.inspur.edp.bef.api.exceptions.ErrorCodes;
import com.inspur.edp.bef.core.action.authorityinfo.BefAuthorityInfo;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.changeListener.EntityDataChangeListener;
import com.inspur.edp.cef.api.changeListener.IChangeHandlerContext;
import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IRootAccessor;
import com.inspur.edp.cef.entity.changeset.AddChangeDetail;
import com.inspur.edp.cef.entity.changeset.ChangeType;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.repository.DataSaveParameter;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;

public class CoreBEContext extends BEContext /*implements ICoreBEContext*/ {

  //region ChangeListener
  private EntityDataChangeListener changeListener;

  private IBEManagerContext privateBEManagerContext;

  public final IBEManagerContext getBEManagerContext() {
    return privateBEManagerContext;
  }

  public final void setBEManagerContext(IBEManagerContext value) {
    privateBEManagerContext = value;
  }

	public final void startChangeListener() {
    if (changeListener == null) {
      changeListener = new EntityDataChangeListener(this);
			}

		changeListener.registListener((IRootAccessor)getCurrentData());
		//((IRootAccessor)BEContext.CurrentData).PropertyChanging += ChangeListener.CurrentData_propertyChanging;
		//((IRootAccessor)BEContext.CurrentData).ItemRemoved += ChangeListener.CurrentData_itemRemoved;
		//((IRootAccessor)BEContext.CurrentData).ItemAdded += ChangeListener.CurrentData_itemAdded;
	}

	public void stopChangeListener() {
	if(changeListener != null){
		changeListener.unregistListener(getCurrentData());
		}
}
	public void restartChangeListener() {
	if (changeListener != null) {
		changeListener = new EntityDataChangeListener(this);
	}
	changeListener.registListener(getCurrentData());
}

  public final void suspendChangeListener() {
    if (changeListener != null) {
      changeListener.suspend();
    }
  }

  public final void resumeChangeListener() {
    if (changeListener != null) {
      changeListener.resume();
    }
  }
  //endregion

  public final void mergeIntoInnerChange() {
    IChangeDetail listenerChange = getListenerChange();
    if (listenerChange != null) {
      getResponse().mergeInnerChange(listenerChange);
    }
  }

	public final void appendTempCurrentChange(IChangeDetail changeDetail)
	{
		getBufferChangeManager().appendCurrentTemplateChange(changeDetail);
		//ChangesetManager.appendCurrentChange(changeDetail);

		suspendChangeListener();
		try
		{
			switch (changeDetail.getChangeType())
			{
				case Modify:
					((IAccessor)getCurrentData()).acceptChange(changeDetail);
					break;
				case Deleted:
					setCurrentData(null);
					break;
				case Added:
					setCurrentData(((AddChangeDetail)changeDetail).getEntityData());
//CurrentData = ((AddChangeDetail)CurrentChange).EntityData;
					break;
				default:
					throw new BefEngineException(ErrorCodes.UnknownChangeType, changeDetail.getChangeType().toString(), null);
			}
		}
		finally
		{
			resumeChangeListener();
		}
	}

	public final void acceptListenerChange()
	{
		getBufferChangeManager().acceptListenerChange(getID());
		//if (ListenerChange == null)
		//    return;
		//ChangesetManager.appendCurrentTemplateChange(ListenerChange);
		//ChangesetManager.appendCurrentChange(ListenerChange);
		//ChangesetManager.acceptListenerChange(ID);
		//ListenerChange = null;
	}

	//提交CurrentChange/CurrentData到Transaction
	public final void acceptChanges()
	{
		acceptTempChange();
		if (getCurrentChange() == null)
		{
			return;
		}
//		IEntityData targetData = getTransactionData();
		suspendChangeListener();
		try {
			setTransactionData(
					(IEntityData) getBufferChangeManager().acceptCurrent(getID()));
		}
		finally{
			resumeChangeListener();
		}
	}

	public final void clearData()
	{
		getBufferChangeManager().rejectBufferZeroLevel(getID());
		setCurrentData(null);
		setTransactionData(null);
		setOriginalData(null);
		changeListener = null;
		multiLanguaged = false;
	}

	public final void rejectChanges()
	{
		IChangeDetail listenerChange = getListenerChange();
		if(listenerChange == null && getCurrentChange() == null){
			return;
		}
		//TODO: 实体动作中属性赋值然后报错, 此时current为null只有listener有值;
		if (listenerChange != null) {
			acceptListenerChange();
		}
		rejectTempChange();
		setCurrentData((IEntityData)getBufferChangeManager().rejectCurrent(getID()));
	}

	public final void acceptTempChange() {
		getBufferChangeManager().acceptCurrentTemplateChange(getID());
	}

	public final void rejectTempChange()
	{
		getBufferChangeManager().rejectCurrentTemplateChange(getID());
	}

	//提交TransactionChange/TransactionData到Original
	public final void acceptTransaction() {
		//TODO:[cef] 为什么要判断currentChange!=null?
		//if (CurrentChange != null)
		//    throw new BefException(ErrorCodes.AcceptingNochangeToTransaction, "当前变更集不存在无法合并");
		IChangeDetail tranChange = getTransactionalChange();
		if (tranChange == null) {
			return;
		}
		if (tranChange.getChangeType() == ChangeType.Deleted) {
			deleted = true;
		}
		setOriginalData((IEntityData)getBufferChangeManager().acceptTransaction(getID()));
	}

	public final void rejectTransactional() {
		rejectTempChange();
		if (getTransactionalChange() == null && getCurrentChange() == null)
		{
			return;
		}
		RefObject<IEntityData> currentRefer = new RefObject<>(null);
		RefObject<IEntityData> tranRefer = new RefObject<>(null);
		getBufferChangeManager().rejectTransaction(getID(), currentRefer, tranRefer);
		setTransactionData(tranRefer.argvalue);
		setCurrentData(currentRefer.argvalue);
						//var transData = TransactionData;
		//EntityDataManager.Instance.rejectChanges(this, ref transData, OriginalData, getTransactionalChange(), true);
		//TransactionData = transData;

		//var currData = CurrentData;
		//EntityDataManager.Instance.rejectChanges(this, ref currData, OriginalData, getTransactionalChange(), false);
		//CurrentData = currData;

		//getTransactionalChange() = null;
	}

  private boolean deleted;

  @Override
  public boolean isDeleted() {
    return deleted || super.isDeleted();
  }

  //是否已执行保存前联动计算
  private boolean privateBeforeSaveDeterminated;

  public final boolean getBeforeSaveDeterminated() {
    return privateBeforeSaveDeterminated;
  }

  public final void setBeforeSaveDeterminated(boolean value) {
    privateBeforeSaveDeterminated = value;
  }

  private boolean versionSetted;

  public final boolean getVersionSetted() {
    return versionSetted;
  }

  public void setVersionSetted(boolean value) {
    versionSetted = value;
  }

  private DataSaveParameter dataSavePar = new DataSaveParameter();

  public DataSaveParameter getDataSavePar() {
    return dataSavePar;
  }

  public Map<String, BefAuthorityInfo> getAuthorityInfos() {
    return getSessionItem().getAuthorityInfos();
  }

  public void addAuthorityInfos(String actionCode, String[] values) {
    getSessionItem().addAuthorityInfos(actionCode, values);
  }

	public boolean hasValues(String actionCode,String[] values)
	{return getSessionItem().hasValues(actionCode,values);
	}

	@Getter
	@Setter
	private boolean multiLanguaged;
}
